/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

//
// Created by Wangyunlai on 2022/5/22.
//

#include "rc.h"
#include "common/log/log.h"
#include "common/lang/string.h"
#include "sql/stmt/filter_stmt.h"
#include "storage/common/db.h"
#include "storage/common/table.h"

// #include "util/date.h"

FilterStmt::~FilterStmt()
{
  for (FilterUnit *unit : filter_units_) {
    delete unit;
  }
  filter_units_.clear();
}

RC FilterStmt::create(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
		      const Condition *conditions, int condition_num,
		      FilterStmt *&stmt)
{
  // 先置rc为SUCCESS
  RC rc = RC::SUCCESS;
  stmt = nullptr;

  // 定义一个tmp_stmt为new FilterStmt()
  FilterStmt *tmp_stmt = new FilterStmt();
  // 这个for循环是用来进行一系列的检查的
  for (int i = 0; i < condition_num; i++) {
    FilterUnit *filter_unit = nullptr;
    rc = create_filter_unit(db, default_table, tables, conditions[i], filter_unit);
    if (rc != RC::SUCCESS) {
      delete tmp_stmt;
      LOG_WARN("failed to create filter unit. condition index=%d", i);
      return rc;
    }
    tmp_stmt->filter_units_.push_back(filter_unit);
  }

  // 检查没问题之后，把new出来的tmp_stmt值传递给stmt
  stmt = tmp_stmt;
  return rc;
}

RC get_table_and_field(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
		       const RelAttr &attr, Table *&table, const FieldMeta *&field)
{
  // 经过一系列的判断之后把各个值进行更新
  if (common::is_blank(attr.relation_name)) {
    table = default_table;
  } else if (nullptr != tables) {
    auto iter = tables->find(std::string(attr.relation_name));
    if (iter != tables->end()) {
      table = iter->second;
    }
  } else {
    table = db->find_table(attr.relation_name);
  }
  if (nullptr == table) {
    LOG_WARN("No such table: attr.relation_name: %s", attr.relation_name);
    return RC::SCHEMA_TABLE_NOT_EXIST;
  }

  field = table->table_meta().field(attr.attribute_name);
  if (nullptr == field) {
    LOG_WARN("no such field in table: table %s, field %s", table->name(), attr.attribute_name);
    table = nullptr;
    return RC::SCHEMA_FIELD_NOT_EXIST;
  }

  return RC::SUCCESS;
}

RC FilterStmt::create_filter_unit(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
				  const Condition &condition, FilterUnit *&filter_unit)
{
  RC rc = RC::SUCCESS;
  
  CompOp comp = condition.comp;
  // 判断比较符号是否符合定义
  if (comp < EQUAL_TO || comp >= NO_OP) {
    LOG_WARN("invalid compare operator : %d", comp);
    return RC::INVALID_ARGUMENT;
  }

  Expression *left = nullptr;
  Expression *right = nullptr;
  if (condition.left_is_attr) {
    Table *table = nullptr;
    const FieldMeta *field = nullptr;
    rc = get_table_and_field(db, default_table, tables, condition.left_attr, table, field);  
    // 获取一下table和field
    // 如果获取成功则继续进行下去，获取没成功则在日志里面输出cannot find attr
    if (rc != RC::SUCCESS) {
      LOG_WARN("cannot find attr");
      return rc;
    }
    left = new FieldExpr(table, field);
  } else {
    if (condition.left_value.type == DATES) {
      if (!check_date(*(int *)(condition.left_value.data))) {
        LOG_WARN("date data is of wrong format");
        rc = RC::INVALID_ARGUMENT;
        return rc;
      }
    }
    left = new ValueExpr(condition.left_value);
  }
  // 经过上面这个if大嵌套的工作之后，left的condition进行了初始化

  if (condition.right_is_attr) {
    Table *table = nullptr;
    const FieldMeta *field = nullptr;
    rc = get_table_and_field(db, default_table, tables, condition.right_attr, table, field);  
    if (rc != RC::SUCCESS) {
      LOG_WARN("cannot find attr");
      delete left;
      return rc;
    }
    right = new FieldExpr(table, field);
  } else {
    // if(condition.right_value.type == CHARS){
    //   //如果是一个chars，我们需要判断它是否是一个date类型的数据
    //   int32_t date = -1;
    //   std::string b;
    //   rc = ValueExpr::value_string_to_date(condition.right_value,b,date);
    //   //如果他是一个date类型的数据，我们会在这里得到rc变成SUCCESS
    //   //所以开始判断
    //   if(rc != RC::SUCCESS){
    //     LOG_INFO("这不是一个date类型的数据");
    //   } 
    //   const char *str = b.c_str();
    //   value_destroy(&condition.right_value);
    //   value_init_date(&condition.right_value,str);
    // } 
    if (condition.right_value.type == DATES) {
      if (!check_date(*(int *)(condition.right_value.data))) {
        LOG_WARN("date data is of wrong format");
        rc = RC::INVALID_ARGUMENT;
        return rc;
      }
    }
    right = new ValueExpr(condition.right_value);
  }
  //这个if跟上面做的工作是一样的

  // 把filterStmt类的几个值都用上面的语句进行了赋值
  // 然后我们声明一个filter_unit
  // 并把上面已经赋值的类成员再传递给filter_unit
  filter_unit = new FilterUnit;
  filter_unit->set_comp(comp);
  filter_unit->set_left(left);
  filter_unit->set_right(right);

  // 检查两个类型是否能够比较
  return rc;
}
